from utils import Operation, Observation
import math
'''
Strategy Design:
Strategy 是所有策略的父亲，不要动Strategy！！！！！！

every_n_day: 数字，每多少天，运行一次策略，every_n_day 应该大于 0 
Operations: Operation组成的列表，你的策略做出的决策应当挂在Operations下，回测系统读到后会进行检查合法性，并进行相应的操作
holdings: 是一个字典，{股票id ： 持有的数量}，注意是股票的数量不是钱，可以有很多对，初始化策略的时候你可以直接持有一定数量的股票
money： 现金，用于购买股票
name： 你的策略的名字，可以不填
Observations： Observation组成的列表，策略必须向回测系统提供需要观测的值，然后才能做出判断，你的申请应当放在Observations里
Observed： 回测系统根据Observations返回的值

strategy函数： 在此处写你的量化策略

所有域和所有的股票id如下
[
'open', 'close', 'high', 'low', 'volume', 'money', 'factor', 'avg', 'pre_close', 'high_limit', 'low_limit', 'paused', 
'change_pct', 'change', 'amplitude', 'up_to_limit', 'down_to_limit', 'is_st', 'boll_down', 'CR20', 'boll_up', 'growth',
 'TRIX5', 'beta', 'VOL5', 'WVAD', 'RSI', 'BBI', 'BIAS', 'MA', 'MTM', 'CCI', 'MACD', 'OBV', 'PSY'
 ]
 
[
'600150.XSHG', '600900.XSHG', '600048.XSHG', '600340.XSHG', '600569.XSHG', '600019.XSHG', '600115.XSHG', '600118.XSHG',
 '600151.XSHG', '002558.XSHE', '603110.XSHG', '000001.XSHE', '600030.XSHG', '601001.XSHG', '002611.XSHE', '601857.XSHG',
  '600028.XSHG', '600050.XSHG', '000063.XSHE', '000651.XSHE', '600111.XSHG', '600518.XSHG', '600056.XSHG', '600519.XSHG'
  ]

'''
class Strategy():
    def __init__(self, every_n_day, holdings={}, money=0):
        self.every_n_day = every_n_day #
        self.Operations = []
        if holdings is dict:
            self.holdings = holdings
        else:
            self.holdings = {}
        self.money = money
        self.name = None
        self.Observations = []
        self.Observed = []

    def strategy(self):
        self.Operations = []


class BaseStrategy(Strategy):
    def __init__(self, every_n_day):
        super(BaseStrategy, self).__init__(every_n_day)
        self.name = "bailan"
        self.holdings = {}
        self.holdings['000001.XSHE'] = 100
'''
如何写一个策略
'''
u=[
'600150.XSHG', '600900.XSHG', '600048.XSHG', '600340.XSHG', '600569.XSHG', '600019.XSHG', '600115.XSHG', '600118.XSHG',
 '600151.XSHG', '002558.XSHE', '603110.XSHG', '000001.XSHE', '600030.XSHG', '601001.XSHG', '002611.XSHE', '601857.XSHG',
  '600028.XSHG', '600050.XSHG', '000063.XSHE', '000651.XSHE', '600111.XSHG', '600518.XSHG', '600056.XSHG', '600519.XSHG'
  ]


class Laba(Strategy):
    '''开口喇叭策略：因上轨和下轨轨迹发生分歧产生，通常发生在底部长时间整理后，信道区间极小。随着成交量释放，股价飙升，上轨随着股价向上，下轨减去标准差后急速下降。
所以在放量的情况下，布林线上轨上行、下轨下行时买入，第二天卖出。'''
    def __init__(self, every_n_day):
        super(Laba, self).__init__(every_n_day)
        self.name = 'LaBa'
        self.holdings = {}
        self.money = 1000000
        self.Observations = []
        for i in range(len(u)):
            self.Observations.append(Observation(u[i], 1, 'close'))
            self.Observations.append(Observation(u[i], 1, 'boll_up'))
            self.Observations.append(Observation(u[i], 1, 'boll_down'))
            self.Observations.append(Observation(u[i], 1, 'MA'))
            self.Observations.append(Observation(u[i], 1, 'volume'))
            self.Observations.append(Observation(u[i], 2, 'close'))
            self.Observations.append(Observation(u[i], 2, 'boll_up'))
            self.Observations.append(Observation(u[i], 2, 'boll_down'))
            self.Observations.append(Observation(u[i], 2, 'MA'))
            self.Observations.append(Observation(u[i], 2, 'volume'))
    def strategy(self):
        self.Operations = []
        l = self.Observed
        ll = []
        nontype=False
        for i in range(0, len(l), 10):
            for t in range(10):
                if l[i + t] is None or math.isnan(l[i + t]):
                    nontype=True
            if nontype==False:
                if l[i + 9] != 0 and l[i+4]>l[i+9]*1.5 and l[i + 2] < l[i + 7]:
                    ll.append(int(i / 10))

        for key in self.holdings.keys():
            self.Operations.append(Operation('sell', key, 1, True))

        if len(ll) > 0:
            for j in ll:
                self.Operations.append(Operation('buy', u[j], 1 / len(ll), True))



class Ma(Strategy):
    '''Ma策略：当k线上穿MA线时买入，第二天卖出'''
    def __init__(self, every_n_day):
        super(Ma, self).__init__(every_n_day)
        self.name = 'MA'
        self.holdings = {}
        self.money = 1000000
        self.Observations=[]
        for i in range(len(u)):
            self.Observations.append(Observation(u[i], 1, 'MA'))
            self.Observations.append(Observation(u[i], 2, 'MA'))
            self.Observations.append(Observation(u[i], 1, 'close'))
            self.Observations.append(Observation(u[i], 2, 'close'))
    def strategy(self):
        self.Operations = []
        l=self.Observed
        ll=[]
        for i in range(0,len(l),4):
            if l[i] is None or math.isnan(l[i]) or l[i+1] is None or math.isnan(l[i+1]) or l[i+2] is None or math.isnan(l[i+2]) or l[i+3] is None or math.isnan(l[i+3]):
                continue
            if l[i]<l[i+2] and l[i+1]>l[i+3]:
                ll.append(i/4)
        for i in self.holdings.keys():
            self.Operations.append(Operation('sell', i, 1, True))
        if len(ll)>0:
            for s in ll:
                self.Operations.append(Operation('buy', u[int(s)], 1/len(ll), True))

class Strategy1(Strategy):
    '''很简单的看涨幅，每次卖出当前股票，买入涨幅最大的那支股票'''
    def __init__(self, every_n_day):
        super(Strategy1, self).__init__(every_n_day)
        self.name = 'yyds' #给这一次运行的策略起个名字
        self.holdings = {}
        self.money = 1000000
        self.Observations = []
        for i in u:
            self.Observations.append(Observation(i, 3, 'close'))
        for t in u:
            self.Observations.append(Observation(t, 1, 'close'))
    def strategy(self):
        self.Operations = []
        istrue=True
        m=-100
        imax=0
        for i in range(len(u)):
            st=self.Observed[i]
            if st is None or math.isnan(st):
                istrue=False

            ed=self.Observed[i+len(u)]
            if ed is None or math.isnan(ed):
                istrue=False
            if istrue==True:
                rate=(ed-st)/st
                if rate>m:
                    m=rate
                    imax=i
        if m>0:
            for key in self.holdings.keys():
                self.Operations.append(Operation('sell', key, 1, True))
            self.Operations.append(Operation('buy', imax, 1, True))

class Strategy2(Strategy):
    '''看RSI指数，小于30就买....结果亏到底裤都不剩了'''
    def __init__(self, every_n_day):
        super(Strategy2, self).__init__(every_n_day)
        self.name = 'awsl' #给这一次运行的策略起个名字
        self.holdings = {}
        self.money = 1000000
        self.Observations = []
        for i in range(len(u)):
            self.Observations.append(Observation(u[i], 1, 'RSI'))
            self.Observations.append(Observation(u[i], 2, 'RSI'))
    def strategy(self):
        self.Operations = []
        obs=self.Observed
        good=[]         #记录该买入股票的序号
        for t in range(0,len(obs),2):
            if obs[t] is None or math.isnan(obs[t]) or obs[t+1] is None or math.isnan(obs[t+1]):
                continue
            if obs[t]<30 and obs[t+1]<30:
                good.append(int(t/2))
        if len(good)>0:
            for key in self.holdings.keys():
                self.Operations.append(Operation('sell', key, 1, True))
            for j in good:
                self.Operations.append(Operation('buy',u[j],1/len(good),True))

class Strategy3(Strategy):
    '''看BBI指标:下跌行情中，若当日收盘价跌破BBI曲线则卖出；上涨行情中，若当日收盘价升越BBI曲线则买入'''
    def __init__(self, every_n_day):
        super(Strategy3, self).__init__(every_n_day)
        self.name = 'kksk' #给这一次运行的策略起个名字
        self.holdings = {}
        self.money = 1000000
        self.Observations = []
        for i in range(len(u)):
            self.Observations.append(Observation(u[i], 1, 'BBI'))
            self.Observations.append(Observation(u[i], 1, 'open'))
            self.Observations.append(Observation(u[i], 1, 'close'))
    def strategy(self):
        self.Operations = []
        obs=self.Observed
        good=[]         #记录该买入股票的序号
        bad=[]
        for t in range(0,len(obs),3):
            if obs[t] is None or math.isnan(obs[t]) or obs[t+1] is None or math.isnan(obs[t+1]) or obs[t+2] is None or math.isnan(obs[t+2]):
                continue
            if obs[t+1]>obs[t] and obs[t]>obs[t+2] and u[int(t/3)] in self.holdings.keys():
                bad.append(int(t/3))
            if obs[t+2]>obs[t] and obs[t]>obs[t+1]:
                good.append(int(t/3))

        if len(good)>0:
            for key in bad:
                self.Operations.append(Operation('sell', u[key], 1, True))
            for j in good:
                self.Operations.append(Operation('buy',u[j],1/len(good),True))

class Strategy4(Strategy):
    '''涨了就买'''
    def __init__(self, every_n_day):
        super(Strategy4, self).__init__(every_n_day)
        self.name = 'lazy' #给这一次运行的策略起个名字
        self.holdings = {}
        self.money = 1000000
        self.Observations = []
        for i in range(len(u)):
            self.Observations.append(Observation(u[i], 1, 'volume'))
            self.Observations.append(Observation(u[i], 1, 'close'))
    def strategy(self):
        self.Operations = []
        obs = self.Observed
        good = []  # 记录该买入股票的序号
        for t in range(0, len(obs), 2):
            if obs[t] is None or math.isnan(obs[t]) or obs[t + 1] is None or math.isnan(obs[t + 1]):
                continue
            if obs[t] < obs[t + 1] and obs[t+1]>obs[t]*1.5:
                good.append(int(t / 2))

        if len(good) > 0:
            for key in self.holdings.keys():
                self.Operations.append(Operation('sell', key, 1, True))
            for j in good:
                self.Operations.append(Operation('buy', u[j], 1 / len(good), True))

class TemplateStrategy(Strategy):#給策略起个名字
    def __init__(self, every_n_day):
        super(TemplateStrategy, self).__init__(every_n_day)
        self.name = 'whatever' #给这一次运行的策略起个名字
        self.holdings = {} # 不给他股票就不要给他
        self.holdings['000001.XSHE'] = 100 #给他100股 000001
        self.money = 0 # 不给他现金

        """
        申请查看数据,先去看utils.py下面的 Observation，了解Observation有什么东西
        """
        #如果你想获取昨天的股票价格（收盘价）
        #输入股票id，1代表1天前，‘close’指昨天的收盘价，
        self.Observations = [
            Observation("股票id", 1, 'close')
        ]
        #如果你想获取很多组数据
        self.Observations = [
            Observation("id", 1, 'MMT'),
            Observation("id2", 2, 'DJAOHFBWO')
        ]
    def strategy(self):
        self.Operations = [] #这一行为了清空之前的操作，不要忘了
        '''
        你的策略从这里开始，首先，你去self.Observed获取你申请的值
        x,y 的顺序就是之前的Observation的顺序
        注意返回的值可能是None, 比如策略申请没有记录的值（如申请十年前的值，没有记录）
        '''
        x,y = self.Observed # 判断 x 是 None : x is None
        # 判断  x 是 nan : math.isnan(x)
        # 请自己做好nan和None的异常处理，最简单的方法当然是如果收到异常值直接跳过这一轮策略，清空Operations即可
        if x < y:
            '''
            去参考utils.py Operations, 逻辑和Observation很像
            一下操作将卖掉一半的id股和买入500元的 id2 股，买入的时候由于钱可能不够买一股会被取整数
            '''

            self.Operations.append(Operation('sell', 'id', 0.5, True))
            self.Operations.append(Operation('buy', 'id2', 500, False))

        """
        你不需要考虑各种数值取证，你就放心买500块，最终结果由量化系统修正
        你也可以卖你没有的股票，反正系统也会忽略
        
        """
